/*
 * Copyright (C) 2006 Google Inc.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package servlets;

import util.RequestUtil;
import util.SamlException;
import util.Util;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * This servlet, part of the SAML-based Single Sign-On Reference Tool, generates
 * a SAML request and then forwards the request to the Identity Provider.
 * <p>
 * <ul>
 * SAML parameters:
 * <p>
 * <li>URI for the Identity Provider's single sign-on service</li>
 * <li>Service Provider's name</li>
 * <li>Relay state URL (end goal URL)</li>
 * <li>Assertion Consumer Service URL</li>
 * <ul>
 * 
 */
public class CreateRequestServlet extends HttpServlet {

	private static final String AUTHN_REQUEST_TEMPLATE = "AuthnRequestTemplate.xml";

	protected void service(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {

		String resourceSite = (String) request.getParameter("resourceSite");

		if ("idp".equals(resourceSite)) {
			String ssoURL = "http://localhost:8088/identityProvider/ProcessRequestServlet";

			String providerName = "serviceProvider";

			String relayStateURL = "http://localhost:8088/serviceProvider/service.jsp";
			String acsURI = "http://localhost:8088/serviceProvider/ACSServlet";

			try {
				String authnRequest = createAuthnRequest(acsURI, providerName);
				String redirectURL = computeURL(ssoURL, authnRequest,
						relayStateURL);
				response.sendRedirect(redirectURL);
			} catch (SamlException e) {
				request.setAttribute("error", e.getMessage());
			}
		}
	}

	/*
	 * Generates a SAML AuthnRequest XML by replacing the specified ACS URL and
	 * provider name in the SAML AuthnRequest template file. Returns the string
	 * format of the XML file.
	 */
	private String createAuthnRequest(String acsURL, String providerName)
			throws SamlException {
		String filepath = getServletContext().getRealPath(
				"templates/" + AUTHN_REQUEST_TEMPLATE);
		String authnRequest = Util.readFileContents(filepath);
		authnRequest = authnRequest.replace("<PROVIDER_NAME>", providerName);
		authnRequest = authnRequest.replace("<ACS_URL>", acsURL);
		authnRequest = authnRequest.replace("<AUTHN_ID>", Util.createID());
		authnRequest = authnRequest.replace("<ISSUE_INSTANT>", Util
				.getDateAndTime());
		return authnRequest;
	}

	/*
	 * Generates the URL to forward the SAML AuthnRequest to the Identity
	 * Provider's single sign-on service.
	 */
	private String computeURL(String ssoURL, String authnRequest,
			String relayStateURL) throws SamlException {
		StringBuffer buf = new StringBuffer();
		try {
			buf.append(ssoURL);

			buf.append("?SAMLRequest=");
			buf.append(RequestUtil.encodeMessage(authnRequest));

			buf.append("&RelayState=");
			buf.append(URLEncoder.encode(relayStateURL, "UTF-8"));
			return buf.toString();
		} catch (UnsupportedEncodingException e) {
			throw new SamlException(
					"Error encoding SAML Request into URL: Check encoding scheme - "
							+ e.getMessage());
		} catch (IOException e) {
			throw new SamlException(
					"Error encoding SAML Request into URL: Check encoding scheme - "
							+ e.getMessage());
		}
	}

	/**
	 * The doPost method handles HTTP POST requests sent to the
	 * CreateRequestServlet. It reads in SAML parameters from request and
	 * generate SAML AuthnRequest to forward to the Identity Provider.
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {

		String action = request.getParameter("action");
		String returnPage = request.getParameter("returnPage");

		// Redirect to servlet at Identity Provider's end to parse AuthnReqest
		// parameters generated by this servlet.
		String ssoURL = "./ProcessResponseServlet";

		// Set the paramaters for AuthnRequest
		String providerName = "google.com";
		String domainName = "psosamldemo.net";
		String relayStateURL = "http://mail.google.com/a/" + domainName;
		String acsURI = "https://www.google.com/a/" + domainName + "/acs";

		String authnRequest;
		String redirectURL;
		try {
			// Create the AuthnRequest XML from above parameters
			authnRequest = createAuthnRequest(acsURI, providerName);
			request.setAttribute("authnRequest", authnRequest);
			// Compute URL to forward AuthnRequest to the Identity Provider
			redirectURL = computeURL(ssoURL, authnRequest, relayStateURL);
			request.setAttribute("redirectURL", redirectURL);

		} catch (SamlException e) {
			request.setAttribute("error", e.getMessage());
		}
		// Else, return generated AuthnRequest for display at Service Provider
		request.getRequestDispatcher(returnPage).include(request, response);
	}

}